#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define CLI_MAX (50)

// 客户端结构体
typedef struct Client
{
 int sock;		//socket 标识符
 pthread_t tid; //线程ID
 char name[20];	//昵称
 struct sockaddr_in addr;
}Client;

Client clients[CLI_MAX];
size_t cnt = 0;

void error_exit(const char* func)
{
	printf("%s:%m\n",func);
	exit(EXIT_FAILURE);
}

void client_send(Client* client,char* buf)
{
	size_t len = strlen(buf)+1;
 	for(int i=0; i<CLI_MAX; i++)
 	{
  		if(clients[i].sock && clients[i].sock != client->sock)
  		{
    		int ret = send(clients[i].sock,buf,len,0);
			if(0 >= ret)
				break;
  		}
 	}
}

void *run(void *arg)
{
	Client* client = arg;
	char buf[4096];
	
	size_t wet = recv(client->sock,client->name,sizeof(client->name),0);
	sprintf(buf,"欢迎%s进入聊天室!!!\n",client->name);
	//sprintf(buf,"%s:%s\n",client->name,buf);
 	client_send(client,buf);

	for (;;)
	{
		// 接收数据
		size_t ret = recv(client->sock,buf,sizeof(buf),0);
		if (0 >= ret || 0 == strcmp("quit", buf))
			break;
		printf("%s:%s\n",client->name,buf);

		// 返回数据
		ret = send(client->sock,buf,strlen(buf)+1,0);
		if (0 >= ret)
			break;
		strcat(buf,"  from:");
  		strcat(buf,client->name);
  		client_send(client,buf);
	}
	printf("%s退出聊天室！\n",client->name);
	// 关闭通信socket
	close(client->sock);
}

int main(int argc,const char* argv[])
{
	if (2 != argc)
	{
		printf("Use:./a.out <port>\n");
		return EXIT_FAILURE;
	}

	// 创建socker对象
	int svr_fd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > svr_fd)
	{
		error_exit("socket");
	}

	// 准备通信地址
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(atoi(argv[1]));
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	socklen_t addrlen = sizeof(addr);

	// 绑定socket对象和通信地址
	if(bind(svr_fd,(struct sockaddr*)&addr,addrlen))
	{
		error_exit("bind");
	}

	// 开启监听
	if(listen(svr_fd,3))
	{
		error_exit("listen");
	}
	
	for(;;)
	{
		// 等待连接
		clients[cnt].sock = accept(svr_fd,NULL,NULL);
		if(0 > clients[cnt].sock)
			error_exit("accept");
		pthread_create(&clients[cnt].tid,NULL,run,&clients[cnt].sock);
		cnt++;
		usleep(1000);
	}
	// 关闭连接socket
	close(svr_fd);
	return EXIT_SUCCESS;
}